<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>信息隐藏</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/global.css') }}">
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://cdn.bootcss.com/mathjax/3.0.5/es5/tex-mml-chtml.js"></script>
    <script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
    <script src="{{ url_for('static', filename='js/navigation.js') }}"> </script>
    <script src="{{ url_for('static', filename='js/main.js') }}"> </script>

</head>

<body>
    <!--TODO: 每页都有相同的导航栏，如何在不同页面复用一份导航栏代码-->
    <!-- 导入复用导航栏 -->
    <div id="navigation"></div>
    <div class="container-fluid">
        <div class="row">
            <div class="bd-sidebar">
                <ul class="section-nav">
                    <li class="toc-entry toc-h2"><a href="#lsb-algorithm"><b>lsb算法</b></a>
                        <ul>
                            <li class="toc-entry toc-h3"><a href="#lsb-algorithm">lsb算法介绍</a></li>
                            <li class="toc-entry toc-h3"><a href="#lsb-analyse">lsb算法分析</a></li>
                            <li class="toc-entry toc-h3"><a href="#lsb-steps">lsb算法步骤</a></li>
                        </ul>
                    </li>
                    <li class="toc-entry toc-h2"><a href="#pvd-algorithm"><b>pvd算法</b></a>
                        <ul>
                            <li class="toc-entry toc-h3"><a href="#pvd-algorithm">pvd算法介绍</a></li>
                            <li class="toc-entry toc-h3"><a href="#pvd-steps">pvd算法步骤</a></li>
                            <li class="toc-entry toc-h3"><a href="#pvd-example">pvd算法例子</a></li>
                        </ul>
                    </li>
                    <li class="toc-entry toc-h2"><a href="#dct-algorithm"><b>dct算法</b></a>
                        <ul>
                            <li class="toc-entry toc-h3"><a href="#dct-algorithm">dct算法介绍</a></li>
                            <li class="toc-entry toc-h3"><a href="#dct-analyse">dct算法分析</a></li>
                            <li class="toc-entry toc-h3"><a href="#dct-implement">dct算法实现</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
            <!--TODO: 页面内容的二级导航功能-->
            <!--TODO: 算法各方面介绍的内容及排版的优化-->
            <!--TODO: 实现类似wiki网站的用户自定义内容编辑界面-->
            <!--TODO: 图片方式嵌入公式，不易修改，扩展性差，增加用代码实现的公式展示功能-->
            <!--TODO: 使用视频方式展示算法原理-->
            <div class="main-content">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 id="lsb-algorithm" class="panel-title">lsb算法介绍</h3>
                    </div>
                    <div class="panel-body">
                        <p class="p1">LSB全称为 Least Significant
                            Bit（最低有效位），是一种常被用做图片隐写的算法。LSB属于空域算法中的一种，是将信息嵌入到图像点中像素位的最低位，以保证嵌入的信息是不可见的，但是由于使用了图像不重要的像素位，算法的鲁棒性差，水印信息很容易为滤波、图像量化、几何变形的操作破坏。
                        </p>
                    </div>
                    <br>
                    <p style="color:black;font-size:18px;">
                        视频展示LSB原理：
                    </p>
                    <!-- 设置一个视频盒子 -->
                    <div class="videoBox">
                        <!-- 引入视频 -->

                        <video poster="{{ url_for('static', filename='picture/LSB-Steganography-Demo.jpg') }}">
                            <source src="{{ url_for('static', filename='picture/LSB-Steganography-Demo.mp') }}" type="video/mp4">
                        </video>
                        <!-- 给视频进度条一个css样式 -->
                        <div class="jindu">
                            <!-- 给视频进度条设置一个当前进度的背景颜色 -->
                            <div class="jinduyanse"></div>
                        </div>
                    </div>
                    <!-- 创建一个开始播放按钮 -->
                    <button class="start">开始播放</button>
                    <div class="panel-heading">
                        <h3 id="lsb-analyse" class="panel-title">
                            lsb算法分析
                        </h3>
                    </div>
                    <div class="panel-body">
                        <p class="p1">PNG和BMP图片中的图像像素一般是有由RGB（RED红 GREEN绿
                            BLUE蓝）三原色组成，每一种颜色占用8位，取值范围为0x00~0xFF，既有2^24种色值。而人类的眼睛可以区分约1000万种不同的颜色，这就意味着人类眼睛无法区分的颜色还有600多万。
                        </p>
              <img src="{{ url_for('static', filename='picture/lsb_1.png') }}" width="500" height="300" class="img-thumbnail" alt="原图片">
                        <p class="p1">当仅仅更改颜色分量的最低位时，人类的眼睛不能区分这前后的变化，LSB就是在该位置存放信息。</p>
              <img src="{{ url_for('static', filename='picture/lsb_2.png') }}" width="500" height="300" class="img-thumbnail" alt="原图片">
                    </div>
                    <div class="panel-heading">
                        <h3 id="lsb-steps" class="panel-title">
                            lsb算法步骤
                        </h3>
                    </div>
                    <div class="panel-body">
                        <p>（1）将图像文件中的所有像素点以RGB形式分隔开，并将各个颜色分量转换成二进制表示。</p>
                        <p>（2）把每个颜色分量值的最后一位全部设置成0，对图像得影响非常细微，不会影响图像的显示格式。</p>
                        <p>（3）信息嵌入：将隐藏信息转化为二进制，并将这些信息依次填入颜色分量的最低位上，即可完成信息的嵌入。</p>
                        <p>（4）信息提取：将图像像素的最低位依次提取出来，并进行拼接，即可得到原始信息。 </p>
                           <p><a href="http://127.0.0.1:5000/lsb.html">点击进行LSB隐写功能实测</a></p>
                    </div>
                </div>
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 id="pvd-algorithm" class="panel-title">pvd算法介绍</h3>
                    </div>
                    <div class="panel-body">
                        <p class="p1">PVD(pixel-value
                            differencing)算法由Wu等人[9]在2003年提出，主要是根据两个相邻像素值的差值特征嵌入秘密消息，如果元素差值较大，就可以嵌入较多的秘密信息，因为人眼对起伏剧烈的区域敏感性较差。该算法很好的考虑了人类视觉系统的特点以及图像的边缘特性，一般在图像的光滑区域嵌入较少量的信息，在边缘区域嵌入更多的信息，因此较大的提高了图像的隐写量。以后的学者沿着这个思想做了很深入的研究。
                        </p>
                    </div>

                    <div class="panel-heading">
                        <h3 id="pvd-steps" class="panel-title">
                            pvd算法步骤
                        </h3>
                    </div>
                    <div class="panel-body">
                        <p>（1）首先对图像划分为双像素块的方式以之字形贯穿图像所有行。</p>
                        <p>（2）选取范围宽度，将0-255分为若干段，例如(8,8,16,32,64,128)。</p>
                        <p>（3）计算每双像素之间的像素差值，记作d。根据d的大小选择范围宽度的上界值<span class="subscript">u<sup1>k</sup1></span>
                            &nbsp;和下届值<span class="subscript">l<sup1>k</sup1></span>&nbsp;&nbsp;,利用式(a)计算出选择嵌入的比特数n。</p>
                        <!-- <img src="./static/picture/pvd_a.png" class="img-thumbnail" alt="原图片"> -->
                        $$ n = \log_2{ (u_k - l_k + 1)} \tag{a}$$

                        <p>（4）从秘密消息中窃取n比特的数据b,计算新的像素差值d'。</p>
                        <!-- <img src="./static/picture/pvd_b.png" class="img-thumbnail" alt="原图片"> -->
                        $$
                        d^{'} =
                        \begin{cases}
                        l_k+b, \quad{......d \ge 0} \\
                        -(l_k+b), \quad{...d \lt 0}
                        \end{cases}
                        \tag{b}
                        $$

                        <p>（5）根据新的像素差值计算新的像素值<span class="subscript">g<sup1>i</sup1></span>'&nbsp;和<span
                                class="subscript">g<sup2>i+1</sup2></span>'&nbsp;&nbsp;&nbsp;&nbsp;具体看公式（c）。</p>
                        <!-- <img src="./static/picture/pvd_c.png" class="img-thumbnail" alt="原图片"> -->
                        $$
                        \begin{equation}
                        \begin{split}
                        f((g_i,g_{i+1}),m)&=(g_i^{'},g_{i+1}^{'})\\
                        &=\begin{cases}
                        (g_i-floor_m,g_{i+1}+celling_m)......当d为偶数时\\[2ex]
                        (g_i-celling_m,g_{i+1}+floor_m)......当d为奇数时
                        \end{cases}\\
                        \end{split}
                        \end{equation}
                        \tag{c}
                        $$
                        $$
                        其中 m=d{'}-d,floor_m= \lfloor \frac{m}{2} \rfloor, celling_m= \lceil \frac{m}{2} \rceil
                        $$

                        <p>（6）越界检查，由于公式（c）存在隐写后数据不在0-255范围间，所以基于公式(d)对图像进行越界检查。</p>
                        <!-- <img src="./static/picture/pvd_d.png" class="img-thumbnail" alt="原图片"> -->
                        $$ (g_i^{'},g_{i+1}^{'})=f((g_i,g_{i+1}),u_k-d) \tag{d} $$

                        <p>当<span class="subscript">g<sup1>i</sup1></span>'&nbsp;和<span class="subscript">g<sup2>i+1
                                </sup2></span>'&nbsp;&nbsp;&nbsp;&nbsp;计算后越界时，则认为存在隐写后越界的可能性，隐写时忽略该像素对隐写数据。</p>

                    </div>
                    <div class="panel-heading">
                        <h3 id="pvd-example" class="panel-title">
                            pvd算法例子
                        </h3>
                    </div>
                    <div class="panel-body">
              <img src="{{ url_for('static', filename='picture/pvd_e.png') }}"  width="600" height="600" class="img-thumbnail" alt="原图片">
                        <p>具体解释：</p>
                        <p>假设一个样本的双像素块的灰度值分别是50和65。</p>
                        <p>（1）根据步骤3，计算出二者之间差值d=15。因为8&lt;d&lt;23，所以选择在8到23的范围宽度。利用公式（a）可知<span class="subscript">u<sup1>
                                    k</sup1></span>&nbsp;&nbsp;-<span class="subscript">l<sup1>k</sup1>
                            </span>&nbsp;&nbsp;+1=23-8+1=16=2^4，得到可嵌入的比特数n为4，意味着属于该范围内的差值可以嵌入四位的秘密数据。</p>
                        <p>（2）根据步骤4，可知隐藏数据前四位二进制为1010，转换为十进制为b=10。由公式（b）可知，本例中的差值d=15大于0，则使用第一种情况，得到d’=<span
                                class="subscript">l<sup1>k</sup1></span>&nbsp;&nbsp;+b=8+10=18(注意不能混淆此处的<span
                                class="subscript">l<sup1>k</sup1></span>&nbsp;&nbsp;是所选择范围的下限，不要以为是原灰度值的下限)。</p>
                        <p>（3）根据步骤5，利用公式（c）计算的m=3，floorm=1，ceilingm=2，因为d=15是奇数，则使用第二种情况，得到新灰度值为(50-2,65+1)=(48,66)。</p>
                           <p><a href="http://127.0.0.1:5000/pvd.html">点击进行PVD隐写功能实测</a></p>
                    </div>
                </div>
                <div class="panel panel-default">
                    <div class="panel-heading">
                        <h3 id="dct-algorithm" class="panel-title">dct算法介绍</h3>
                    </div>
                    <div class="panel-body">
                        <p class="p1">DCT变换的全称是离散余弦变换，主要用于将数据或图像的压缩，能够将空域的信号转换到频域上，具有良好的去相关性的性能。DCT变换本身是无损的，但是在图像编码等领域给接下来的量化、哈弗曼编码等创造了很好的条件，同时，由于DCT变换是对称的，所以，我们可以在量化编码后利用DCT反变换，在接收端恢复原始的图像信息。DCT变换在当前的图像分析已经压缩领域有着极为广大的用途，我们常见的JPEG静态图像编码以及MJPEG、MPEG动态编码等标准中都使用了DCT变换。
                        </p>
                    </div>
                    <div class="panel-heading">
                        <h3 id="dct-analyse" class="panel-title">
                            dct算法分析
                        </h3>
                    </div>
                    <div class="panel-body">
                        <h5 style="font-weight: bold;">一维DCT变换</h5>
                        <p class="p1">一维DCT变换时二维DCT变换的基础，所以我们先来讨论下一维DCT变换。一维DCT变换共有8种形式，其中最常用的是第二种形式，由于其运算简单、适用范围广。其表达式如下：</p>
                        <!-- <img src="./static/picture/dct_1.png" class="img-thumbnail" alt="原图片">-->
                        $$
                        F(u)=c(u)\sum_{i=0}^{N-1}f(i)cos\begin{bmatrix}\frac{(i+0.5)\pi}{N}u\end{bmatrix}
                        $$
                        $$
                        c(u) =
                        \begin{cases}
                        \sqrt{\frac 1N}, u=0 \\[2ex]
                        \sqrt{\frac 2N}, u\neq0
                        \end{cases}
                        $$
                        <p>其中，f(i)为原始的信号，F(u)是DCT变换后的系数，N为原始信号的点数，c(u)可以认为是一个补偿系数，可以使DCT变换矩阵为正交矩阵。</p>
                    </div>
                    <div class="panel-body">
                        <h5 style="font-weight: bold;">二维DCT变换</h5>
                        <p class="p1">二维DCT变换其实是在一维DCT变换的基础上在做了一次DCT变换，其公式如下：</p>
                        <!-- <img src="./static/picture/dct_1.png" class="img-thumbnail" alt="原图片"> -->
                        $$
                        F(u,v)=c(u)c(v)\sum_{i=0}^{N-1}\sum_{j=0}^{N-1}f(i,j)cos\begin{bmatrix}\frac{(i+0.5)\pi}{N}u\end{bmatrix}cos\begin{bmatrix}\frac{(j+0.5)\pi}{N}v\end{bmatrix}
                        $$
                        $$
                        c(u) =
                        \begin{cases}
                        \sqrt{\frac 1N}, u=0 \\[2ex]
                        \sqrt{\frac 2N}, u\neq0
                        \end{cases}
                        $$

                        <p>由公式我们可以看出，上面只讨论了二维图像数据为方阵的情况，在实际应用中，如果不是方阵的数据一般都是补齐之后再做变换的，重构之后可以去掉补齐的部分，得到原始的图像信息。</p>
                    </div>
                    <div class="panel-body">
                        <h5 style="font-weight: bold;">二维DCT反变换</h5>
                        <p class="p1">在图像的接收端，根据DCT变化的可逆性，我们可以通过DCT反变换恢复出原始的图像信息，其公式如下：</p>
                        <!-- <img src="./static/picture/dct_3.png" class="img-thumbnail" alt="原图片"> -->
                        $$
                        f(i,j)=\sum_{u=0}^{N-1}\sum_{v=0}^{N-1}c(u)c(v)F(u,v)cos\begin{bmatrix}\frac{(i+0.5)\pi}{N}u\end{bmatrix}cos\begin{bmatrix}\frac{(j+0.5)\pi}{N}v\end{bmatrix}
                        $$
                        $$
                        c(u) =
                        \begin{cases}
                        \sqrt{\frac 1N}, u=0 \\[2ex]
                        \sqrt{\frac 2N}, u\neq0
                        \end{cases}
                        $$

                    </div>
                    <div class="panel-heading">
                        <h3 id="dct-implement" class="panel-title">
                            dct算法的实现
                        </h3>
                    </div>
                    <div class="panel-body">
                        <p>（1） 隐写算法先将载体图像划分成连续的8×8的子块。</p>
                        <p>（2） 对每个子块使用二维DCT变换获得新的子块。将过程定义为下述公式:</p>
                        <!-- <img src="./static/picture/dct_2.png" class="img-thumbnail" alt="原图片"> -->
                        $$
                        F(u,v)=c(u)c(v)\sum_{i=0}^{N-1}\sum_{j=0}^{N-1}f(i,j)cos\begin{bmatrix}\frac{(i+0.5)\pi}{N}u\end{bmatrix}cos\begin{bmatrix}\frac{(j+0.5)\pi}{N}v\end{bmatrix}
                        $$
                        $$
                        c(u) =
                        \begin{cases}
                        \sqrt{\frac 1N}, u=0 \\[2ex]
                        \sqrt{\frac 2N}, u\neq0
                        \end{cases}
                        $$

                        <p class="p1">图像DCT变换后有如下特征：
                        <p>
                        <ul>
                            <li>一个图像的DCT低频系数分布在DCT系数矩阵的左上角，高频系数分布在右下角；</li>
                            <li>低频系数的绝对值大于高频系数的绝对值</li>
                            <li>图像低频部分集中了图像大部分能量，鲁棒性强但不可见性差；</li>
                            <li>图像高频部分集中了图像的细节，不可见性强但鲁棒性差。</li>
                        </ul>
                        <p>（3）
                            将秘密消息进行隐写以后对DCT子块系数进行扫描，判断该DCT系数的绝对值是否等于1或者0，若等于则跳过嵌入步骤，反之判断秘密消息的比特或者DCT系数的最低有效位是否相同，相同则不更改，不同则将DCT系数的最低有效位替换成秘密消息的比特。
                        </p>
                        <p>（4） 将嵌入秘密信息后的DCT系数进行二维DCT逆变换，完成隐写。</p>
                           <p><a href="http://127.0.0.1:5000/dct.html">点击进行DCT隐写功能实测</a></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>
